package com.rs.game.player.content;

import com.rs.cache.loaders.ItemDefinitions;
import com.rs.game.Animation;
import com.rs.game.Graphics;
import com.rs.game.World;
import com.rs.game.WorldTile;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.controlers.Wilderness;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;

/*
 * content package used for static stuff
 */
public class Magic {
	
	private static final int
	AIR_RUNE = 556,
	WATER_RUNE = 555,
	EARTH_RUNE = 557,
	FIRE_RUNE = 554,
	
	MIND_RUNE = 558,
	CHAOS_RUNE = 562,
	DEATH_RUNE = 560,
	BLOOD_RUNE = 565,
			
	LAW_RUNE = 563;
	

	
	public static final boolean hasInfiniteRunes(int runeId, int weaponId) {
		if(runeId == AIR_RUNE) {
			if(weaponId == 1381) //air staff
				return true;
		}else if (runeId == WATER_RUNE) {
			if(weaponId == 1383) //water staff
				return true;
		}else if (runeId == EARTH_RUNE) {
			if(weaponId == 1385) //water staff
				return true;
		}else if (runeId == FIRE_RUNE) {
			if(weaponId == 1387)
				return true;
		}
		return false;
	}

	public static final boolean checkCombatSpell(Player player, int spellId, int set, boolean delete) {
		switch(player.getCombatDefinitions().getSpellBook()) {
		case 192:
			switch(spellId) {
			case 25:
				if(!checkSpellRequiriments(player, 1, delete, AIR_RUNE, 1, MIND_RUNE, 1))
					return false;
			break;
			case 28:
				if(!checkSpellRequiriments(player, 5, delete, WATER_RUNE, 1, AIR_RUNE, 1, MIND_RUNE, 1))
					return false;
			break;
			case 30:
				if(!checkSpellRequiriments(player, 9, delete, EARTH_RUNE, 2, AIR_RUNE, 1, MIND_RUNE, 1))
					return false;
			break;
			case 32:
				if(!checkSpellRequiriments(player, 13, delete, FIRE_RUNE, 3, AIR_RUNE, 2, MIND_RUNE, 1))
					return false;
			break;
			case 34: //air bolt
				if(!checkSpellRequiriments(player, 17, delete, AIR_RUNE, 2, CHAOS_RUNE, 1))
					return false;
			case 39: //water bolt
				if(!checkSpellRequiriments(player, 23, delete, WATER_RUNE, 2, AIR_RUNE, 2, CHAOS_RUNE, 1))
					return false;
				break;
			case 42: //earth bolt
				if(!checkSpellRequiriments(player, 29, delete, EARTH_RUNE, 3, AIR_RUNE, 2, CHAOS_RUNE, 1))
					return false;
				break;
			case 45: //fire bolt
				if(!checkSpellRequiriments(player, 35, delete, FIRE_RUNE, 4, AIR_RUNE, 3, CHAOS_RUNE, 1))
					return false;
				break;
			case 49: //air blast
				if(!checkSpellRequiriments(player, 41, delete, AIR_RUNE, 3, DEATH_RUNE, 1))
					return false;
				break;
			case 52: //water blast
				if(!checkSpellRequiriments(player, 47, delete, WATER_RUNE, 3, AIR_RUNE, 3, DEATH_RUNE, 1))
					return false;
				break;
			case 58: //earth blast
				if(!checkSpellRequiriments(player, 53, delete, EARTH_RUNE, 4, AIR_RUNE, 3, DEATH_RUNE, 1))
					return false;
				break;
			case 63: //fire blast
				if(!checkSpellRequiriments(player, 59, delete, FIRE_RUNE, 5, AIR_RUNE, 4, DEATH_RUNE, 1))
					return false;
				break;
			case 70: //air wave
				if(!checkSpellRequiriments(player, 62, delete, AIR_RUNE, 5, BLOOD_RUNE, 1))
					return false;
				break;
			case 73: //water wave
				if(!checkSpellRequiriments(player, 65, delete, WATER_RUNE, 7, AIR_RUNE, 5, BLOOD_RUNE, 1))
					return false;
				break;
			case 77: //earth wave
				if(!checkSpellRequiriments(player, 70, delete, EARTH_RUNE, 7, AIR_RUNE, 5, BLOOD_RUNE, 1))
					return false;
				break;
			case 80: //fire wave
				if(!checkSpellRequiriments(player, 75, delete, FIRE_RUNE, 7, AIR_RUNE, 5, BLOOD_RUNE, 1))
					return false;
				break;
			default:
				return false;
			}
			break;
		default:
			return false;
		}
		if(set >= 0) {
			if(set == 0)
				player.getCombatDefinitions().setAutoCastSpell(spellId);
			else
				player.getTemporaryAttributtes().put("tempCastSpell", spellId);
		}
		return true;
	}
	
	public static final void setCombatSpell(Player player, int spellId) {
		if(player.getCombatDefinitions().getAutoCastSpell() == spellId)
			player.getCombatDefinitions().resetSpells(true);
		else
			checkCombatSpell(player, spellId, 0, false);
		player.stopAll();
	}
	
	public static final void processNormalSpell(Player player, int spellId, int packetId) {
		switch(spellId) {
		case 25: //air strike
		case 28: //water strike
		case 30: //earth strike
		case 32: //fire strike
		case 34: //air bolt
		case 39: //water bolt
		case 42: //earth bolt
		case 45: //fire bolt
		case 49: //air blast
		case 52: //water blast
		case 58: //earth blast
		case 63: //fire blast
		case 70: //air wave
		case 73: //water wave
		case 77: //earth wave
		case 80: //fire wave
			setCombatSpell(player, spellId);
		break;
		case 27: //crossbow bolt enchant
			if(player.getSkills().getLevel(Skills.MAGIC) < 4) {
				player.getPackets().sendGameMessage("Your Magic level is not high enougth for this spell.");
				return;
			}
			player.stopAll();
			player.getInterfaceManager().sendInterface(432);
		break;
		case 37: //mobi
			sendNormalTeleportSpell(player, 10, 19, new WorldTile(2413, 2848, 0)
			, LAW_RUNE, 1, WATER_RUNE, 1, AIR_RUNE, 1);
		break;
		case 40: //varrock
			sendNormalTeleportSpell(player, 25, 19, new WorldTile(3212, 3424, 0)
			,  FIRE_RUNE, 1, AIR_RUNE, 3, LAW_RUNE, 1);
		break;
		case 43: //lumby
			sendNormalTeleportSpell(player, 31, 41, new WorldTile(3222, 3218, 0)
			,  EARTH_RUNE, 1, AIR_RUNE, 3, LAW_RUNE, 1);
			break;
		case 46: //fally
			sendNormalTeleportSpell(player, 37, 48, new WorldTile(2964, 3379, 0)
			,  WATER_RUNE, 1, AIR_RUNE, 3, LAW_RUNE, 1);
			break;
		case 51: //camelot
			sendNormalTeleportSpell(player, 45, 55.5, new WorldTile(2757, 3478, 0)
			,  AIR_RUNE, 5, LAW_RUNE, 1);
			break;
		case 57: //ardy
			sendNormalTeleportSpell(player, 51, 61, new WorldTile(2664, 3305, 0)
			,  WATER_RUNE, 2, LAW_RUNE, 2);
			break;
		case 62: //watch
			sendNormalTeleportSpell(player, 58, 68, new WorldTile(2757, 3478, 0)
			,  EARTH_RUNE, 2, LAW_RUNE, 2);
			break;
		case 69: //troll
			sendNormalTeleportSpell(player, 61, 68, new WorldTile(2911, 3610, 0)
			,  FIRE_RUNE, 2, LAW_RUNE, 2);
			break;
		case 72: //ape
			sendNormalTeleportSpell(player, 64, 76, new WorldTile(2776, 9103, 0)
			,  FIRE_RUNE, 2, WATER_RUNE,2, LAW_RUNE, 2, 1963, 1);
			break;
		}
	}
	
	
	public static final boolean checkSpellRequiriments(Player player, int level, boolean delete, int...runes) {
		if(player.getSkills().getLevel(Skills.MAGIC) < level) {
			player.getPackets().sendGameMessage("Your Magic level is not high enougth for this spell.");
			return false;
		}
		return checkRunes(player, delete, runes);
	}
	
	
	public static final boolean checkRunes(Player player, boolean delete, int... runes) {
		int weaponId = player.getEquipment().getWeaponId();
		int runesCount = 0;
		while(runesCount < runes.length) {
			int runeId = runes[runesCount++];
			int ammount = runes[runesCount++];
			if(hasInfiniteRunes(runeId, weaponId))
				continue;
			if(!player.getInventory().containsItem(runeId, ammount)) {
				player.getPackets().sendGameMessage("You do not have enougth "+ItemDefinitions.getItemDefinitions(runeId).getName().replace("rune", "Rune")+"s to cast this spell.");
				return false;
			}
		}
		if(delete) {
			runesCount = 0;
			while(runesCount < runes.length) {
				int runeId = runes[runesCount++];
				int ammount = runes[runesCount++];
				if(hasInfiniteRunes(runeId, weaponId))
						continue;
				player.getInventory().deleteItem(runeId, ammount);
			}
		}
		return true;
	}
	
	public static final void sendNormalTeleportSpell(Player player, int level, double xp, WorldTile tile, int... runes) {
		sendTeleportSpell(player, 8939, 8941, 1576, 1577, level, xp, tile, runes);
	}
	public static final void sendTeleportSpell(final Player player, int upEmoteId, final int downEmoteId, int upGraphicId, final int downGraphicId, int level, final double xp, final WorldTile tile, int... runes) {
		long currentTime = System.currentTimeMillis();
		if(player.getStopDelay() > currentTime)
			return;
		if(player.getSkills().getLevel(Skills.MAGIC) < level) {
			player.getPackets().sendGameMessage("Your Magic level is not high enougth for this spell.");
			return;
		}
		if(player.getFreezeDelay() >= currentTime) {
			player.getPackets().sendGameMessage("A magical force stops you from moving.");
			return;
		}
		if(!player.getControlerManager().processMagicTeleport(tile))
			return;
		if(!checkRunes(player, true, runes))
			return;
		
		player.stopAll();
		//TODO controler check, usefull for minis
		if(upEmoteId != -1)
			player.setNextAnimation(new Animation(upEmoteId));
		if(upGraphicId != -1)
			player.setNextGraphics(new Graphics(upGraphicId));
		player.addStopDelay(7);
		WorldTasksManager.schedule(new WorldTask() {
			boolean firstStage = true;
			@Override
			public void run() {
				if(player.isDead()) {
					stop();
					return;
				}
				if(firstStage) {
					firstStage = false;
					WorldTile teleTile = tile;
					//attemps to randomize tile by 4x4 area
					for(int trycount = 0; trycount < 10; trycount++) {
						teleTile = new WorldTile(tile, 2);
						int regionId = teleTile.getRegionId();
						int baseLocalX = teleTile.getX() - ((regionId >> 8) * 64) ;
						int baseLocalY = teleTile.getY() - ((regionId & 0xff) * 64);
						if(World.getRegion(regionId).getObject(tile.getPlane(), baseLocalX, baseLocalY) == null)
							break;
					}
					player.setNextWorldTile(teleTile);
					player.setNextFaceWorldTile(new WorldTile(teleTile.getX(), teleTile.getY()-1, teleTile.getPlane()));
					if(Wilderness.isAtWild(teleTile))
						player.getControlerManager().startControler("Wilderness");
					player.setDirection(6);
					player.getSkills().addXp(Skills.MAGIC, xp);
				}else{
					if(downEmoteId != -1)
						player.setNextAnimation(new Animation(downEmoteId));
					if(downGraphicId != -1)
						player.setNextGraphics(new Graphics(downGraphicId));
					stop();
				}
			}
		}, 3,0);
		
	
	}
	
	private Magic() {
		
	}
}
